package com.threeti.mecool.core.application;

import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class Cache {
    static final String NULL = "";
    private Map<String, Object> data = new ConcurrentHashMap<String, Object>();

    public void set(String key, Object val) {
        data.put(key, val);
    }

    public Object get(String key) {
        return data.get(key);
    }

    public Object get(String key, String generatorCheckingKey, Generator generator, String...generatorArgs) {
        if (!data.containsKey(generatorCheckingKey) && generator != null) {
            Map<String, Object> values = generator.get(generatorArgs);
            data.put(generatorCheckingKey, NULL);
            for (Map.Entry<String, Object> kv : values.entrySet()) {
                Object value = kv.getValue();
                data.put(kv.getKey(), value != null ? value : NULL);
            }
        }
        return get(key);
    }

    public boolean has(String key) {
        return data.containsKey(key);
    }

    public boolean has(String key, String generatorCheckingKey, Generator generator, String...generatorArgs) {
        if (!data.containsKey(generatorCheckingKey) && generator != null) {
            Map<String, Object> values = generator.get(generatorArgs);
            data.put(generatorCheckingKey, NULL);
            for (Map.Entry<String, Object> kv : values.entrySet()) {
                Object value = kv.getValue();
                data.put(kv.getKey(), value != null ? value : NULL);
            }
        }
        return data.containsKey(key);
    }

    public Object remove(String key) {
        return data.remove(key);
    }

    public void removeByPrefix(String prefix) {
        Iterator<String> keyIterator = data.keySet().iterator();
        while (keyIterator.hasNext()) {
            String key = keyIterator.next();
            if (key.startsWith(prefix)) {
                data.remove(key);
            }
        }
    }

    public static interface Generator {
        Map<String, Object> get(String...key);
    }
}
